﻿using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace AutoCADDotNetLibrary.Analyzers.Analyzers
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class CommandMethodAttributeAnalyzer : DiagnosticAnalyzer
    {
        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ACDiagnostic.Rule_CommandMethodAttribute_Repeat);

        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            context.RegisterCompilationStartAction(compilationStartAnalysisContext =>
            {
                if (!Helper.GetEnableAutoCADAnalyzers(compilationStartAnalysisContext.Options))
                    return;

                //得到所有命令方法
                List<(string Command, Location Location)> globalNameList = new List<(string Command, Location Location)>();
                compilationStartAnalysisContext.RegisterSymbolAction(symbolAnalysisContext =>
                {
                    AttributeData att = symbolAnalysisContext.Symbol.GetAttributes()
                     .Where(x => x.AttributeClass.ToDisplayString() == "Autodesk.AutoCAD.Runtime.CommandMethodAttribute").FirstOrDefault();
                    if (att == null)
                        return;

                    AttributeSyntax attSyntax = att.ApplicationSyntaxReference.GetSyntax(compilationStartAnalysisContext.CancellationToken) as AttributeSyntax;

                    string command = "";
                    Location location = Location.None;
                    if (att.ConstructorArguments.Length <= 2)
                    {
                        if (att.ConstructorArguments.Length > 0)//第一个参数为globalName
                        {
                            command = att.ConstructorArguments[0].Value?.ToString() ?? "";
                            location = attSyntax.ArgumentList.Arguments[0].GetLocation();
                        }
                    }
                    else//第二个参数为globalName
                    {
                        command = att.ConstructorArguments[1].Value?.ToString() ?? "";
                        location = attSyntax.ArgumentList.Arguments[1].GetLocation();
                    }

                    //被命名的参数位置可能不同
                    AttributeArgumentSyntax nameColon = attSyntax.ArgumentList.Arguments.FirstOrDefault(x => x?.NameColon?.Name?.ToString() == "globalName");
                    if (nameColon != null)
                    {
                        location = nameColon.GetLocation();
                    }

                    lock (globalNameList)
                    {
                        globalNameList.Add((command, location));
                    }
                }, SymbolKind.Method);

                compilationStartAnalysisContext.RegisterCompilationEndAction(symbolAnalysisContext =>
                {
                    globalNameList.GroupBy(x => x.Command.Trim().ToLower()).Where(x => x.Count() > 1)
                    .SelectMany(x => x).ToList().ForEach(x =>
                    {
                        symbolAnalysisContext.ReportDiagnostic(Diagnostic.Create(ACDiagnostic.Rule_CommandMethodAttribute_Repeat, x.Location, x.Command));
                    });
                });
            });
        }
    }
}